from article.models import Article, Category, Tag, Avatar
from rest_framework import serializers

from user_info.serializers import UserDescSerializer
from comment.serializers import CommentSerializer

# class ArticleListSerializer(serializers.ModelSerializer):
#   # id = serializers.IntegerField(read_only=True)
#   # title = serializers.CharField(allow_blank=True, max_length=100)
#   # body = serializers.CharField(allow_blank=True)
#   # created = serializers.DateTimeField()
#   # modified = serializers.DateTimeField()
#   # read_only 参数设置为只读
#   author = UserDescSerializer(read_only=True)
#   # 新增字段，添加超链接
#   # HyperlinkedIdentityField 是 DRF 框架提供的超链接字段，只需要你在参数里提供路由的名称，它就自动帮你完成动态地址的映射。
#   # view_name 是路由的名称，也就是我们在 path(... name='xxx') 里的那个 name
#   url = serializers.HyperlinkedIdentityField(view_name='article:detail')

#   class Meta:
#     model = Article
#     fields = [
#       # 'id',
#       'title',
#       'author',
#       'created',
#       'url',
#     ]
#     # 指定只读字段
#     # read_only_fields = ['author']

# class ArticleDetailSerializer(serializers.ModelSerializer):
#   class Meta:
#     model = Article
#     fields = '__all__'

class ArticleCategoryDetailSerializer(serializers.ModelSerializer):
  """给分类详情的嵌套序列化器"""
  url = serializers.HyperlinkedIdentityField(view_name='article-detail')

  class Meta:
    model = Article
    fields = [
      'url',
      'title'
    ]

class CategoryDetailSerializer(serializers.ModelSerializer):
  """分类详情"""
  articles = ArticleCategoryDetailSerializer(many=True, read_only=True)
  
  class Meta:
    model = Category
    fields = [
      'id',
      'title',
      'created',
      'articles',
    ]

class CategorySerializer(serializers.ModelSerializer):
  """分类的序列化器"""
  create_by = UserDescSerializer(read_only=True)
  modifier = UserDescSerializer(read_only=True)
  url = serializers.HyperlinkedIdentityField(view_name='category-detail')
  class Meta:
    model = Category
    fields = '__all__'
    read_only_fields = ['ceated', 'modified']

class TagSerializer(serializers.ModelSerializer):
  """标签序列化器"""
  url = serializers.HyperlinkedIdentityField(view_name='tag-detail')

  def check_tag_obj_exists(self, validated_data):
    text = validated_data.get('text')
    if Tag.objects.filter(text=text).exists():
      raise serializers.ValidationError(f'Tag with text {text} exists.')
  
  def create(self, validated_data):
    self.check_tag_obj_exists(validated_data)
    return super().create(validated_data)
  
  def update(self, instance, validated_data):
    self.check_tag_obj_exists(validated_data)
    return super().update(instance, validated_data)

  class Meta:
    model = Tag
    fields = [
      'id',
      'text',
      'url'
    ]

class AvatarSerializer(serializers.ModelSerializer):
  url = serializers.HyperlinkedIdentityField(view_name='avatar-detail')

  class Meta:
    model = Avatar
    fields = [
      'id', 'url', 'content'
    ]

class ArticleBaseSerializer(serializers.HyperlinkedModelSerializer):
  id = serializers.IntegerField(read_only=True)
  author = UserDescSerializer(read_only=True)
  # category 的嵌套序列化字段
  category = CategorySerializer(read_only=True)
  # category 的 id 字段，用于创建/更新 category 外键
  category_id = serializers.IntegerField(write_only=True, allow_null=True, required=False)
  # SlugRelatedField 是不允许有重复的 slug_field
  tags = serializers.SlugRelatedField(
    queryset=Tag.objects.all(),
    many=True,
    required=False,
    slug_field='text'
  )
  # 图片字段
  avatar = AvatarSerializer(read_only=True)
  avatar_id = serializers.IntegerField(
    write_only=True,
    allow_null=True,
    required=False
  )

  created = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)

  # 自定义错误信息
  default_error_messages = {
    'incorrect_avatar_id': 'Avatar with id {value} not exists.',
    'incorrect_category_id': 'Category with id {value} not exists.',
    'default': 'No more message here..'
  }

  def check_obj_exists_or_fail(self, model, value, message='default'):
    if not self.default_error_messages.get(message, None):
      message = 'default'
    
    if not model.objects.filter(id=value).exists() and value is not None:
      self.fail(message, value=value)

  # 验证图片 id 是否存在, 不存在则返回验证错误
  def validate_avatar_id(self, value):
    self.check_obj_exists_or_fail(model=Avatar, value=value, message='incorrect_avatar_id')
    return value

  # 覆写方法，如果输入的标签不存在则创建它
  def to_internal_value(self, data):
    tags_data = data.get('tags')
    if isinstance(tags_data, list):
      for text in tags_data:
        if not Tag.objects.filter(text=text).exists():
          Tag.objects.create(text=text)
    
    return super().to_internal_value(data)
  
  # category_id 字段的验证器
  def validate_category_id(self, value):
    self.check_obj_exists_or_fail(model=Avatar, value=value, message='incorrect_category_id')
    return value


class ArticleSerializer(ArticleBaseSerializer):
  class Meta:
    model = Article
    fields = '__all__'
    extra_kwargs = {'body': {'write_only': True}}


class ArticleDetailSerializer(ArticleBaseSerializer):
  # id = serializers.IntegerField(read_only=True)
  # 渲染后的正文
  body_html = serializers.SerializerMethodField()
  # 渲染后的目录
  toc_html = serializers.SerializerMethodField()

  comments = CommentSerializer(many=True, read_only=True)

  def get_body_html(self, obj):
    return obj.get_md()[0]
  
  def get_toc_html(self, obj):
    return obj.get_md()[1]
  
  class Meta:
    model = Article
    fields = '__all__'
